package com.ztgf.logistics.service.deppon;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.ztgf.common.constant.Result;
import com.ztgf.common.enums.CodeEnum;
import com.ztgf.common.utils.DateUtils;
import com.ztgf.common.utils.StrUtils;
import com.ztgf.dubbo.exception.ServiceException;
import com.ztgf.file.models.bo.FileInfoSaveBO;
import com.ztgf.file.models.service.IFileService;
import com.ztgf.file.models.vo.FileInfoVO;
import com.ztgf.logistics.models.dto.deppon.*;
import com.ztgf.logistics.models.service.deppon.*;
import com.ztgf.shopping.models.dto.shop.ShopSysInvoiceDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.apache.poi.ss.usermodel.*;
import org.springframework.beans.BeanUtils;
import javax.annotation.Resource;
import com.ztgf.logistics.common.config.YmlConfig;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.ztgf.logistics.mapper.deppon.LogisticsBillPlatMapper;
import com.ztgf.logistics.models.bo.deppon.LogisticsBillPlatSaveBO;
import org.springframework.scheduling.annotation.Async;
import org.springframework.transaction.annotation.Transactional;

import java.io.ByteArrayInputStream;
import java.math.BigDecimal;
import java.util.*;


/**
 * 物流平台账单表控制器
 *
 * @author mxli
 * @Date 2021-09-13 22:15:41
 */
@Slf4j
@DubboService
public class LogisticsBillPlatServiceImpl extends ServiceImpl<LogisticsBillPlatMapper, LogisticsBillPlatDTO> implements ILogisticsBillPlatService{

    @Resource
    private YmlConfig ymlConfig;
    @Resource
    private ILogisticsBillOrderDepponSnapshotService logisticsBillOrderDepponSnapshotService;

    @Resource
    private ILogisticsBillService logisticsBillService;
    @Resource
    private ILogisticsOrderService logisticsOrderService;
    @Resource
    private ILogisticsUserService logisticsUserService;
    @DubboReference
    private IFileService fileService;


    @Override
    @Transactional(rollbackFor = ServiceException.class)
    public Result add(LogisticsBillPlatSaveBO saveBO, byte[] input, FileInfoSaveBO fileSaveBO) {
        if(saveBO.getEndTime() == null || saveBO.getStartTime() == null){
            return new Result(CodeEnum.FAIL_100002);
        }
        Wrapper wrapper = new EntityWrapper();
        wrapper.ge("start_time", saveBO.getStartTime());////大于等于
        wrapper.le("start_time", saveBO.getEndTime());////大于等于
        wrapper.orNew();
        wrapper.ge("end_time", saveBO.getStartTime());//小于等于
        wrapper.le("end_time", saveBO.getEndTime());//小于等于
        wrapper.last("limit 1");
        LogisticsBillPlatDTO dto = this.selectOne(wrapper);
        if(dto != null){
            return new Result(CodeEnum.FAIL_DEPPON_400012);
        }
        dto = new LogisticsBillPlatDTO();
        //上传文件
        try {
            FileInfoVO vo = fileService.uploadFile(fileSaveBO);
            dto.setFileUrl(vo.getFileUrl());
        } catch (Exception e) {
            log.error("上传文件错误", e);
            return new Result(CodeEnum.FAIL_100006);
        }

        BeanUtils.copyProperties(saveBO,dto);
        Long id = ymlConfig.getPkId();
        dto.setId(id);
        Result<List<LogisticsBillOrderDepponSnapshotDTO>> listResult = this.expalinExcle(input,id);
        if (!listResult.success()) {
            return listResult;
        }
        List<LogisticsBillOrderDepponSnapshotDTO> list = listResult.getData();
        if(list == null || list.size() == 0) {
            return new Result(CodeEnum.FAIL_DEPPON_400009);
        }
        BigDecimal depponMoney = new BigDecimal(0.00);
        BigDecimal money = new BigDecimal(0.00);
        for (LogisticsBillOrderDepponSnapshotDTO snapshotDTO : list) {
            LogisticsOrderDTO orderDTO = logisticsOrderService.getByMailNo(snapshotDTO.getMailNo());
            int status = 1;
            String remark = "无订单";
            depponMoney = depponMoney.add(snapshotDTO.getDepponMoney());
            if (orderDTO != null){
                BigDecimal noBillMoney = orderDTO.getTotalPrice().subtract(orderDTO.getBillPrice());
                if(snapshotDTO.getDepponMoney().compareTo(noBillMoney) == 0) {//相等
                    status = 0;
                    remark = "";
                    money = money.add(noBillMoney);
                } else {
                    remark = "金额不对";
                }

                snapshotDTO.setMoney(noBillMoney);
                snapshotDTO.setOrderId(orderDTO.getId());
                if(orderDTO.getUserType() == 0) {
                    snapshotDTO.setUserId(orderDTO.getShopId());
                    snapshotDTO.setUserName(orderDTO.getShopName());
                } else {
                    snapshotDTO.setUserId(orderDTO.getCreateUserId());
                    snapshotDTO.setUserName(orderDTO.getCreateUserName());
                }
                snapshotDTO.setMemberType(orderDTO.getUserType());
            }
            snapshotDTO.setStatus(status);
            snapshotDTO.setRemark(remark);
        }

        int billStatus = 1;
        if(depponMoney.compareTo(money) == 0) {
            billStatus = 0;
        }
        dto.setDepponMoney(depponMoney);
        dto.setMoney(money);
        dto.setStatus(billStatus);
        //生成账单
        boolean flag = this.insert(dto);
        if (!flag){
            return new Result<>(CodeEnum.FAIL_100007);
        }
        flag = logisticsBillOrderDepponSnapshotService.insertBatch(list);
        if (!flag){
            throw new ServiceException(CodeEnum.FAIL_100007);
        }
        return new Result<>();
    }

    @Override
    @Transactional(rollbackFor = ServiceException.class)
    public void saveSure(Long id) {
        LogisticsBillPlatDTO platDTO = this.selectById(id);
        Wrapper wrapper = new EntityWrapper();
        wrapper.eq("bill_plat_id", id);
        wrapper.eq("sure_status", 0);
        List<LogisticsBillOrderDepponSnapshotDTO> snapshotDTOList = logisticsBillOrderDepponSnapshotService.selectList(wrapper);
        if(snapshotDTOList != null && snapshotDTOList.size() > 0){
            List<LogisticsBillDTO> billList = new ArrayList<>();
            Map<Long, LogisticsBillDTO> billMap = new HashMap<>();

            for(LogisticsBillOrderDepponSnapshotDTO snapshotDTO : snapshotDTOList){
                Long billId = null;
                if(snapshotDTO.getOrderId() != null){
                    LogisticsBillDTO billDTO = billMap.get(snapshotDTO.getUserId());
                    if(billDTO == null){
                        billDTO = new LogisticsBillDTO();
                        billDTO.setId(ymlConfig.getPkId());
                        billDTO.setBillPlatId(platDTO.getId());
                        billDTO.setShopId(snapshotDTO.getUserId());
                        billDTO.setShopName(snapshotDTO.getUserName());
                        billDTO.setStartTime(platDTO.getStartTime());
                        billDTO.setEndTime(platDTO.getEndTime());
                        billDTO.setMoney(snapshotDTO.getMoney());
                        billDTO.setDepponMoney(snapshotDTO.getDepponMoney());
                        billDTO.setMemberType(snapshotDTO.getMemberType());
//                        billDTO.setOverdueTime(DateUtils.addDay(DateUtils.getDayEnd(DateUtils.getFirstDayOfMonth(new Date())), 10));//逾期时间
                        billDTO.setOverdueTime(DateUtils.getMonthEnd(new Date()));//逾期时间:当月最后一天
                        billMap.put(snapshotDTO.getUserId(), billDTO);
                        billList.add(billDTO);
                        if(snapshotDTO.getMemberType() == 0){//修改临时现接
                            LogisticsUserDTO userDTO = new LogisticsUserDTO();
                            userDTO.setStatus(1);
                            userDTO.setId(snapshotDTO.getUserId());
                            boolean flag = logisticsUserService.updateById(userDTO);
                            if(!flag){
                                throw new ServiceException(CodeEnum.FAIL_100008);
                            }
                        }
                    } else {
                        BigDecimal depponMoney = billDTO.getDepponMoney().add(snapshotDTO.getDepponMoney());
                        BigDecimal money = billDTO.getMoney().add(snapshotDTO.getMoney());
                        billDTO.setDepponMoney(depponMoney);
                        billDTO.setMoney(money);
                    }

                    //修改order
                    boolean flag = logisticsOrderService.updateBillMoney(snapshotDTO.getOrderId(), snapshotDTO.getMoney());
                    if(!flag){
                        throw new ServiceException(CodeEnum.FAIL_100008);
                    }

                    billId = billDTO.getId();
                }
                LogisticsBillOrderDepponSnapshotDTO newSnapshotDTO = new LogisticsBillOrderDepponSnapshotDTO();
                newSnapshotDTO.setId(snapshotDTO.getId());
                newSnapshotDTO.setBillId(billId);
                newSnapshotDTO.setSureStatus(1);
                boolean flag = logisticsBillOrderDepponSnapshotService.updateById(newSnapshotDTO);
                if(!flag){
                    throw new ServiceException(CodeEnum.FAIL_100008);
                }
            }
            if(billList.size() > 0){
                boolean flag = logisticsBillService.insertBatch(billList);
                if(!flag){
                    throw new ServiceException(CodeEnum.FAIL_100008);
                }
            }
        }

    }

    @Override
    @Transactional
    public Result delete(Long id) {
        Wrapper wrapper = new EntityWrapper();
        wrapper.eq("id", id);
        wrapper.in("sure_status", "0,3");
        boolean flag = this.delete(wrapper);
        if (flag){
            wrapper = new EntityWrapper();
            wrapper.eq("bill_plat_id", id);
            logisticsBillOrderDepponSnapshotService.delete(wrapper);
            return new Result<>();
        } else {
            return new Result<>(CodeEnum.FAIL_100009);
        }

    }

    private Result<List<LogisticsBillOrderDepponSnapshotDTO>> expalinExcle(byte[] input, Long id){
        ByteArrayInputStream inputStream = new ByteArrayInputStream(input);
        List<LogisticsBillOrderDepponSnapshotDTO> list = new ArrayList<>();
        try {
            Workbook workbook = WorkbookFactory.create(inputStream);
            inputStream.close();
            // 获取工作表对象
            for (int k = 0; k< workbook.getNumberOfSheets(); k++) {
                Sheet sheet = workbook.getSheetAt(k);
                if(!("本期零担明细".equalsIgnoreCase(sheet.getSheetName())
                        || "本期快递明细".equalsIgnoreCase(sheet.getSheetName())
                        || "本期整车明细".equalsIgnoreCase(sheet.getSheetName()))){
                    continue;
                }
                int totalRow = sheet.getPhysicalNumberOfRows();
                int totalCell = sheet.getRow(1).getPhysicalNumberOfCells();
                Row oneRow = sheet.getRow(1);
                for (int i = 2; i < totalRow; i++) {
                    Row row = sheet.getRow(i);
                    LogisticsBillOrderDepponSnapshotDTO dto = new LogisticsBillOrderDepponSnapshotDTO();
                    for (int j = 0; j < totalCell; j++) {
                        String title = oneRow.getCell(j).getStringCellValue().trim();
                        Cell cell = row.getCell(j);
                        cell.setCellType(CellType.STRING);
                        String value = cell.getStringCellValue();
                        switch (title) {
                            case "渠道单号":
                                if(StrUtils.isNotEmpty(value)){
                                    dto.setLogisticId(value.trim());
                                }
                                break;
                            case "业务日期":
                                if(StrUtils.isNotEmpty(value)){
                                    dto.setOrderTime(value.trim());
                                }
                                break;
                            case "运单号":
                                if(StrUtils.isNotEmpty(value)){
                                    dto.setMailNo(value.trim());
                                }
                                break;
                            case "总金额":
                                if(StrUtils.isNotEmpty(value)){
                                    dto.setDepponMoney(new BigDecimal(value.trim()));
                                } else {
                                    dto.setDepponMoney(BigDecimal.valueOf(0.00));
                                }
                                break;

                            default:
                                break;
                        }
                    }
                    if(StrUtils.isEmpty(dto.getMailNo()) || StrUtils.isEmpty(dto.getOrderTime())) {
                        return new Result(CodeEnum.FAIL_DEPPON_400011);
                    }
                    dto.setId(ymlConfig.getPkId());
                    dto.setBillPlatId(id);
                    list.add(dto);
                }
            }


        } catch (Exception e) {
            log.error("解析excel错误", e);
            return new Result(CodeEnum.FAIL_DEPPON_400010);
        }

        return new Result<>(list);
    }
}
